package com.hd123.rumba.util.jpg;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Properties;
import java.util.Vector;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.FileImageInputStream;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.hd123.rumba.util.Progress;
import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class ProcessJpg {

  public static void main(String[] args) throws Exception {
    if (args == null || args.length % 2 != 1) {
      printUsage(null);
    } else {
      Properties props = new Properties();
      String command = args[0];
      for (int i = 1; i < args.length; i += 2)
        props.put(args[i], args[i + 1]);
      if ("thumbnailize".equalsIgnoreCase(command)) {
        String source = props.getProperty("-source");
        String target = props.getProperty("-target");
        String max = props.getProperty("-max", "160");
        String fileName = props.getProperty("-index", "index.html");
        String columns = props.getProperty("-column", "4");
        if (source == null || target == null) {
          printUsage("缺少-source或-target参数");
        } else {
          thumbnailize(source, target, Integer.parseInt(max));
          createIndex(target, fileName, Integer.parseInt(columns), source);
        }
      } else if ("index".equalsIgnoreCase(command)) {
        String source = props.getProperty("-source");
        String href = props.getProperty("-href");
        String fileName = props.getProperty("-index", "index.html");
        String columns = props.getProperty("-column", "4");
        if (source == null) {
          printUsage("缺少-source参数");
        } else {
          createIndex(source, fileName, Integer.parseInt(columns), href);
        }
      } else if ("test".equalsIgnoreCase(command)) {
        File file = new File(props.getProperty("-file"));
        test(file);
      } else {
        printUsage(null);
      }
    }
  }

  public static void printUsage(String error) {
    if (error != null) {
      System.out.println("错误: " + error);
      System.out.println();
    }
    System.out.println("用法: 命令 参数 ... ");
    System.out.println("thumbnailize -source -target -max -index -colum");
    System.out.println("  将-source指定的文件或目录中的所有jpg文件(包括子目录)生成缩略图到-target指定的目录中.");
    System.out.println("  -source x: 源文件或目录");
    System.out.println("  -target x: 目标目录. 如果不存在, 则自动创建");
    System.out.println("  -max x: 缩略图的最大高度或宽度. 缺省值160");
    System.out.println("  -index x: 索引文件名. 缺省值index.html");
    System.out.println("  -column x: 索引文件中每行列数. 缺省值4");
    System.out.println("例如: thumbnailize -source c:\\source -target c:\\target -max 80");
    System.out.println();
    System.out.println("index -source -href -index -column");
    System.out.println("  为-source指定的目录中的所有jpg文件(包括子目录)生成htm索引文件.");
    System.out.println("  -source x: 缩略图目录名");
    System.out.println("  -href x: 源图片目录名. 可不指定.");
    System.out.println("  -index x: 索引文件名. 缺省值index.html");
    System.out.println("  -column x: 索引文件中每行列数. 缺省值4");
    System.out.println("例如: index -source c:\\target");
    System.out.println();
    if (error != null) {
      System.out.println("错误: " + error);
    }
  }

  public static void createTo(File file) throws ImageFormatException, IOException {
    FileOutputStream out = new FileOutputStream(file);
    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
    BufferedImage img = new BufferedImage(640, 480, BufferedImage.TYPE_INT_RGB);
    Graphics2D g = (Graphics2D) img.getGraphics();
    g.setColor(Color.GREEN);
    g.fillRect(0, 0, 640, 480);
    g.setColor(Color.BLUE);
    g.fillOval(100, 100, 400, 200);
    encoder.encode(img);
    out.close();
  }

  /**
   * 将source文件或目录中的所有文件(包括子目录)生成缩略图到target目录中
   * 
   * @param source
   * @param target
   * @param max
   *            缩略图最大宽度或高度
   * @throws ImageFormatException
   * @throws IOException
   */
  public static void thumbnailize(String source, String target, int max)
      throws ImageFormatException, IOException {
    if (source.endsWith("/") || source.endsWith("\\"))
      source = source.substring(0, source.length() - 1);
    File sourceFile = new File(source);
    if (!sourceFile.exists()) {
      throw new IOException(source + " 不存在");
    }
    if (sourceFile.isFile()) {
      if (!sourceFile.getName().toLowerCase().endsWith("jpg")) {
        throw new IOException(source + " 不是jpg文件.");
      }
    }
    File targetFile = new File(target);
    if (!targetFile.exists())
      targetFile.mkdirs();
    Vector<FilePair> filePairs = new Vector();
    createFilePairs(new File(source), new File(target), filePairs, new File(source));
    Progress progress = new Progress();
    progress.setStartTime(new Date());
    progress.setCount(filePairs.size());
    for (int i = 0; i < filePairs.size(); ++i) {
      FilePair filePair = filePairs.get(i);
      if (!filePair.target.getParentFile().exists())
        filePair.target.getParentFile().mkdirs();
      System.out.println(filePair);
      thumbnailize(filePair.source, filePair.target, max);
      progress.setProgress(progress.getProgress() + 1);
      System.out.println(progress.getProgress() + " of " + progress.getCount() + ", "
          + Progress.tohms(progress.estimatedRemainTime()) + " remain");
    }
    System.out.println("共转换了" + filePairs.size() + "个文件．");
  }

  public static File createIndex(String dir, String fileName, int columnCount, String href)
      throws IOException {
    Vector<FilePair> filePairs = new Vector();
    File dirFile = new File(dir);
    int baseLength = dirFile.getAbsolutePath().length() + 1;
    File hrefFile = href == null ? dirFile : new File(href);
    createFilePairs(dirFile, hrefFile, filePairs, dirFile);
    File indexFile = new File(dir, fileName);
    FileOutputStream index = new FileOutputStream(indexFile);
    index
        .write(("<html>\n<head>\n<style>\ntd{font-family:verdana;font-size:9pt}\n</style>\n<head>\n"
            + "<body>\n<table width=100%>\n").getBytes());
    int count = 0;
    File folder = null;
    for (int i = 0; i < filePairs.size(); ++i) {
      FilePair filePair = filePairs.get(i);
      if (!filePair.source.getParentFile().equals(folder)) {
        if (folder != null)
          index.write("</tr>\n".getBytes());
        index.write(("<tr><td style=\"background-color:#0000ff;color:white\" colspan="
            + columnCount + ">" + filePair.source.getParent().substring(baseLength) + "</td></tr>")
            .getBytes());
        folder = filePair.source.getParentFile();
        count = 0;
      }
      if (count % columnCount == 0)
        index.write("<tr>\n".getBytes());
      String s = "<td align=center><a href=\"" + filePair.target.getAbsolutePath()
          + "\"><img src=\"" + filePair.source.getAbsolutePath().substring(baseLength)
          + "\"></img></a><br>" + filePair.source.getName() + "</td>\n";
      index.write(s.getBytes());
      ++count;
      if (count % columnCount == 0) {
        index.write("</tr>\n".getBytes());
        count = 0;
      }
    }
    if (count != 0)
      index.write("</tr>\n".getBytes());
    index.write("</table>\n</body>\n</html>\n".getBytes());
    System.out.println("索引文件: " + indexFile.getAbsolutePath() + "已生成. 共有" + filePairs.size()
        + "个图片文件.");
    return indexFile;
  }

  private static void createFilePairs(File source, File target, Vector<FilePair> filePairs,
      File root) {
    if (source.isDirectory()) {
      File[] files = source.listFiles();
      for (int i = 0; i < files.length; ++i) {
        if (files[i].isDirectory())
          createFilePairs(files[i], target, filePairs, root);
      }
      for (int i = 0; i < files.length; ++i) {
        if (files[i].isFile())
          createFilePairs(files[i], target, filePairs, root);
      }
    } else {
      File outFile;
      if (root.isFile())
        outFile = new File(target, source.getName());
      else
        outFile = new File(target, source.getAbsolutePath().substring(
            root.getAbsolutePath().length() + 1));
      if (outFile.getName().toLowerCase().endsWith(".jpg"))
        filePairs.add(new FilePair(source, outFile));
    }
  }

  private static class FilePair {
    File source;
    File target;

    FilePair(File source, File target) {
      this.source = source;
      this.target = target;
    }

    public String toString() {
      return source.getAbsolutePath() + "->" + target.getAbsolutePath();
    }
  }

  /**
   * 将文件inFile重整大小到outFile
   * 
   * @param inFile
   * @param outFile
   * @param width
   * @param height
   * @throws ImageFormatException
   * @throws IOException
   */
  public static void thumbnailize(File inFile, File outFile, int max) throws ImageFormatException,
      IOException {
    Image src = javax.imageio.ImageIO.read(inFile);
    int sw = src.getWidth(null);
    int sh = src.getHeight(null);
    int w = 0, h = 0;
    if (sw > sh) {
      w = max;
      h = w * sh / sw;
    } else {
      h = max;
      w = h * sw / sh;
    }
    BufferedImage tag = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
    tag.getGraphics().drawImage(src, 0, 0, w, h, null);
    FileOutputStream out = new FileOutputStream(outFile);
    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
    encoder.encode(tag);
    out.close();
  }

  public static void test(File inFile) throws IOException {
    ImageReader reader = (ImageReader) ImageIO.getImageReadersByFormatName("jpeg").next();
    reader.setInput(new FileImageInputStream(inFile));
    IIOMetadata meta = reader.getImageMetadata(0);
    String[] names = meta.getMetadataFormatNames();
    for (int i = 0; names != null && i < names.length; ++i) {
      Node node = meta.getAsTree(names[i]);
      printNode(node, 2);
    }
    Node node = meta.getAsTree("Make");
    printNode(node, 2);
    reader.dispose();
  }

  private static void printNode(Node node, int indent) {
    for (int i = 0; i < indent; ++i)
      System.out.print(" ");
    if (node == null)
      System.out.println("null");
    else {
      System.out.println(node.getNodeName() + "=" + node.getNodeValue() + " ");
      NodeList children = node.getChildNodes();
      for (int i = 0; children != null && i < children.getLength(); ++i)
        printNode(children.item(i), indent + 2);
    }
  }
}
